"use client";
import {
  useAnalysisChainWithFile,
  useAnalysisChainWithID,
  useUploadFile,
} from "@/service/align";
import { useInputLoadStore } from "@/store/input";
import { useCountStore } from "@/store/task";
import { InboxOutlined } from "@ant-design/icons";
import AccountTreeIcon from "@mui/icons-material/AccountTree";
import FormatAlignCenterIcon from "@mui/icons-material/FormatAlignCenter";
import FormatAlignLeftIcon from "@mui/icons-material/FormatAlignLeft";
import NavigationIcon from "@mui/icons-material/Navigation";
import SendIcon from "@mui/icons-material/Send";
import { LoadingButton } from "@mui/lab";
import Box from "@mui/material/Box";
import Fab from "@mui/material/Fab";
import Paper from "@mui/material/Paper";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import ToggleButton from "@mui/material/ToggleButton";
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
import Typography from "@mui/material/Typography";
import { styled } from "@mui/material/styles";
import type { GetProp, UploadProps } from "antd";
import { Upload, message } from "antd";
import React from "react";
import { useImmer } from "use-immer";
import InputTable from "../components/InputTable";

const names = [
  "A",
  "B",
  "C",
  "Ralph Hubbard",
  "Omar Alexander",
  "Carlos Abbott",
  "Miriam Wagner",
  "Bradley Wilkerson",
  "Virginia Andrews",
  "Kelly Snyder",
];

interface Data {
  id: number | string;
  name: string;
  chain: string;
  uploadWay: string;
}

function createData(
  id: number | string,
  name: string,
  chain: string,
  uploadWay: string
): Data {
  return {
    id,
    name,
    chain,
    uploadWay,
  };
}

const { Dragger } = Upload;

const Item = styled(Paper)(({ theme }) => ({
  backgroundColor: theme.palette.mode === "dark" ? "#1A2027" : "#fff",
  ...theme.typography.body2,
  padding: theme.spacing(1),
  textAlign: "center",
  color: theme.palette.text.secondary,
  flexGrow: 1,
}));

const FILE_UPLOAD = "file";
const PDB_UPLOAD = "pdbID";
type FileType = Parameters<GetProp<UploadProps, "beforeUpload">>[0];
export default function StepOne(props: any) {
  const { inputRows, setInputRows } = useInputLoadStore();
  const [uploadWay, setUploadWay] = useImmer({
    inputWay: FILE_UPLOAD,
    currentFileId: 0,
    chain: "A",
    currentFileName: "",
  });

  const [uploadPDBWay, setUploadPDBWay] = useImmer({
    inputWay: PDB_UPLOAD,
    currentPDBId: "",
    chain: "",
  });

  const { mutateAsync: uploadFile, isPending: uploadFileLoading } =
    useUploadFile();

  const {
    mutateAsync: analysisChainWithFile,
    isPending: analysisChainLoading,
  } = useAnalysisChainWithFile();

  const {
    mutateAsync: analysisChainWithID,
    isPending: analysisChainPIDLoading,
  } = useAnalysisChainWithID();
  const { pushFileIds, pushPDBIds } = useCountStore();

  const handlePDBLoad = async () => {
    if (!uploadPDBWay.currentPDBId) {
      message.info("Please fill in the PBD ID");
      return;
    }

    if (!uploadPDBWay.chain) {
      message.info("Please select a chain");
      return;
    }

    if (uploadPDBWay.currentPDBId.length != 4) {
      message.info("The pdb id contains 4 characters");
      return;
    }

    try {
      const resp = await analysisChainWithID({
        pdb_id: uploadPDBWay.currentPDBId,
        chain: uploadPDBWay.chain,
      });
      const pdb_id = resp.id;
      message.success("Protein file loaded successfully");
      pushPDBIds(pdb_id);
      setUploadPDBWay((draft) => {
        draft.chain = "";
        draft.currentPDBId = "";
      });
      setInputRows(
        createData(
          uploadPDBWay.currentPDBId,
          uploadPDBWay.currentPDBId,
          uploadPDBWay.chain,
          uploadPDBWay.inputWay
        )
      );
    } catch (err: any) {
      console.log(err);
      if (err?.response?.data?.message) {
        message.error(err.response.data.message);
      } else {
        message.error("Protein file loading failed");
      }
    }
  };

  const handleFileLoad = async () => {
    if (!uploadWay.currentFileId) {
      message.info("Please upload the file first");
      return;
    }

    if (!uploadWay.chain) {
      message.info("Please select a chain");
      return;
    }

    try {
      await analysisChainWithFile({
        file_id: uploadWay.currentFileId,
        chain: uploadWay.chain,
      });
      message.success("Protein file loaded successfully");
      pushFileIds(uploadWay.currentFileId);
      setUploadWay((draft) => {
        draft.chain = "A";
        draft.currentFileId = 0;
      });
      setInputRows(
        createData(
          uploadWay.currentFileId,
          uploadWay.currentFileName,
          uploadWay.chain,
          uploadWay.inputWay
        )
      );
    } catch (err: any) {
      if (err?.response?.data?.message) {
        message.error(err.response.data.message);
      } else {
        message.error("Protein file loading failed");
      }
    }
  };

  const fileProps: UploadProps = {
    name: "file",
    accept: ".pdb",
    maxCount: 1,
    async onChange(info) {
      let formData = new FormData();
      formData.append("file", info.file as FileType);
      if (!info.fileList.length) {
        return;
      }

      try {
        const uploadFileResp = await uploadFile(formData);
        setUploadWay((draft) => {
          draft.currentFileId = uploadFileResp.id;
          draft.currentFileName = info.file.name;
        });
        message.success("File upload successful");
      } catch (err: any) {
        if (err?.response?.data?.message) {
          message.error(err.response.data.message);
        } else {
          message.error("File upload failed");
        }
      }
    },
    beforeUpload() {
      return false;
    },
  };
  const [alignment, setAlignment] = React.useState<string | null>("left");
  const handleChangeInputWay = (mode: string) => {
    setUploadWay((draft) => {
      draft.inputWay = mode;
    });
  };

  const handleAlignment = (
    event: React.MouseEvent<HTMLElement>,
    newAlignment: string | null
  ) => {
    setAlignment(newAlignment);
  };
  return (
    <Stack spacing={{ xs: 1, sm: 2 }} direction="row" flexWrap="nowrap">
      <Item sx={{ width: "50%", position: "relative" }}>
        <Typography
          sx={{ flex: "1 1 100%", marginTop: "1rem", marginBottom: "1rem" }}
          variant="h6"
          component="div"
        >
          Structure <Box component="span">Prepare</Box>
        </Typography>
        <ToggleButtonGroup
          value={alignment}
          exclusive
          color="primary"
          onChange={handleAlignment}
          sx={{
            borderRadius: "6px",
          }}
        >
          <ToggleButton
            value="left"
            onClick={() => handleChangeInputWay(FILE_UPLOAD)}
            sx={{
              textTransform: "none",
              paddingLeft: "2rem",
              paddingRight: "2rem",
            }}
          >
            <FormatAlignLeftIcon sx={{ marginRight: "12px" }} /> File Upload
          </ToggleButton>
          <ToggleButton
            value="center"
            onClick={() => handleChangeInputWay(PDB_UPLOAD)}
            sx={{
              textTransform: "none",
              paddingLeft: "2rem",
              paddingRight: "2rem",
            }}
          >
            <FormatAlignCenterIcon sx={{ marginRight: "12px" }} /> PDB ID Upload
          </ToggleButton>
        </ToggleButtonGroup>

        <Box
          sx={{
            marginTop: "2rem",
            position: "relative",
            height: "350px",
          }}
        >
          {uploadWay.inputWay == "file" ? (
            <Box sx={{ padding: "0 2rem" }}>
              <Dragger {...fileProps}>
                <p className="ant-upload-drag-icon">
                  <InboxOutlined />
                </p>
                <p className="ant-upload-text">
                  Click or drag file to this area to upload
                </p>
                <p className="ant-upload-hint">
                  Upload the Structure file (PDB) <br />
                  <span style={{ color: "" }}>Not more than 10 proteins</span>
                </p>
              </Dragger>
              <Box
                sx={{
                  display: "flex",
                  alignContent: "center",
                  marginTop: "2rem",
                }}
              >
                <TextField
                  label="Input a chain (eg. A)"
                  variant="standard"
                  value={uploadWay.chain}
                  onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
                    setUploadWay((draft) => {
                      draft.chain = event.target.value.trim();
                    });
                  }}
                  size="medium"
                  fullWidth
                />
                <LoadingButton
                  size="large"
                  color="primary"
                  variant="contained"
                  sx={{
                    textTransform: "none",
                    padding: "0 2rem",
                    marginLeft: "1rem",
                    borderRadius: "12px",
                    position: "relative",
                    top: "0.1rem",
                  }}
                  loading={analysisChainLoading}
                  onClick={handleFileLoad}
                >
                  <NavigationIcon sx={{ mr: 1 }} />
                  Load
                </LoadingButton>
              </Box>
            </Box>
          ) : (
            <Box sx={{ padding: "0 2rem" }}>
              <Box
                sx={{
                  display: "flex",
                  alignItems: "flex-end",
                }}
              >
                <AccountTreeIcon
                  sx={{ color: "action.active", mr: 1, my: 0.5 }}
                />
                <TextField
                  id="input-with-sx"
                  label="PDB ID eg: 7CWZ"
                  variant="standard"
                  sx={{ flex: "1" }}
                  value={uploadPDBWay.currentPDBId}
                  onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
                    setUploadPDBWay((draft) => {
                      draft.currentPDBId = event.target.value.trim();
                    });
                  }}
                />
              </Box>
              <Box
                sx={{
                  display: "flex",
                  alignContent: "center",
                  marginTop: "2rem",
                }}
              >
                <TextField
                  label="Input a chain (eg. A)"
                  variant="standard"
                  value={uploadPDBWay.chain}
                  onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
                    setUploadPDBWay((draft) => {
                      draft.chain = event.target.value.trim();
                    });
                  }}
                  size="medium"
                  fullWidth
                />
                <LoadingButton
                  size="large"
                  color="primary"
                  variant="contained"
                  sx={{
                    textTransform: "none",
                    padding: "0 2rem",
                    marginLeft: "1rem",
                    borderRadius: "12px",
                    position: "relative",
                    top: "0.1rem",
                  }}
                  loading={analysisChainPIDLoading}
                  onClick={handlePDBLoad}
                >
                  <NavigationIcon sx={{ mr: 1 }} />
                  Load
                </LoadingButton>
              </Box>
            </Box>
          )}
          <Fab
            variant="extended"
            sx={{
              marginTop: "2rem",
              background: "rgb(245,245,245)",
              "&:hover": {
                background: "rgb(224,224,224)",
              },
              paddingLeft: "2rem",
              paddingRight: "2rem",
              position: "absolute",
              bottom: "0",
              left: "50%",
              transform: "translateX(-50%)",
            }}
            onClick={() => {
              if (!inputRows.length) {
                message.warning("Please load at least one input.");
                return;
              }
              if (inputRows.length >= 10) {
                message.warning("The number of structures entered exceeds 10.");
                return;
              }
              props.handleNextStep(0);
            }}
          >
            <SendIcon sx={{ mr: 1 }} />
            Next Step
          </Fab>
        </Box>
      </Item>
      <Item sx={{ width: "50%" }}>
        <InputTable dataSource={inputRows} />
      </Item>
    </Stack>
  );
}
